 /*
 * BlobPtr.h
 *
 *  Created on: 2020年12月14日
 *      Author: san
 */

#ifndef BLOBPTR_H_
#define BLOBPTR_H_

#include <vector>
#include <memory>
#include <exception>

#include "Blob.h"

namespace san {

template <typename T>
class BlobPtr {
public:
	BlobPtr(): curr(0) {};
	BlobPtr(Blob<T> &a, size_t sz = 0): wptr(a.data), curr(sz) {}
	virtual ~BlobPtr();
	// 解引用
	T &operator *() const;
	// ++ -- 前置
	BlobPtr<T> &operator ++();
	BlobPtr<T> &operator --();
	// ++ -- 后置
	BlobPtr<T> &operator ++(int);

private:
	std::shared_ptr<std::vector<T>> check(std::size_t, const std::string &msg) const;
	std::size_t curr;
	std::weak_ptr<std::vector<T>> wptr;
};

template <typename T>
BlobPtr<T>::~BlobPtr() {
	// TODO Auto-generated destructor stub
}

template <typename T>
std::shared_ptr<std::vector<T>> BlobPtr<T>::check(size_t i, const std::string &msg) const
{
	// 检查是否越界
	auto ret = wptr->lock();
	if (!ret)
		throw std::runtime_error("unbound weak ptr");
	if (i >= ret->size())
		throw std::out_of_range("index past end");
	return ret;
}

template <typename T>
T &BlobPtr<T>::operator *() const
{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator ++()
{
	// 前置递增
	check(curr, "increment past end!");
	++curr;
	return *this;
}

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator --()
{
	// 前置递减
	if (curr > 0)
		--curr;
	return *this;
}

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator ++(int)
{
	// 前置递增
	BlobPtr<T> ret = *this;
	++*this;
	return ret;
}

} /* namespace san */

#endif /* BLOBPTR_H_ */
